package com.ygqh.baby.service.task.impl;

import com.ygqh.baby.ao.TaskMethod;
import com.ygqh.baby.ao.YgQuartzJob;
import com.ygqh.baby.model.YgProduct4ListModel;
import com.ygqh.baby.po.YgProduct;
import com.ygqh.baby.po.YgProductSecond;
import com.ygqh.baby.service.*;
import com.ygqh.baby.service.task.YgProductSecondTaskService;
import com.ygqh.baby.utils.DateConvertUtils;
import com.ygqh.baby.utils.ExceptionUtil;
import com.ygqh.baby.utils.MailUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.*;

@Service
public class YgProductSecondTaskServiceImpl implements YgProductSecondTaskService {
	protected final Logger logger = Logger.getLogger(this.getClass());

	@Autowired
	private YgTaskTimeService ygTaskTimeService;
	@Autowired
	private YgProductSecondService ygProductSecondService;
	@Autowired
	private YgProductService ygProductService;
	@Autowired
	private MailUtil mailUtil;
	@Autowired
	private RedisCacheEvictService redisCacheEvictService;
	@Autowired
	private ScheduleJobService scheduleJobService;

	@Override
	public void changeProductPriceBySecond() {
		System.out.println("秒杀活动更新商品价格任务启动");
		Date runTime = new Date();
		try {
			Date preDate = DateConvertUtils.addDay(runTime, -1);
			updateSecondPriceToSalePrice(preDate);
			updateSalePriceToSecondPrice(runTime);
			ygTaskTimeService.saveOrUpdate(TaskMethod.ChangeProductPriceBySecond.name(), runTime, "【秒杀活动更新商品价格】执行成功");
		} catch (Exception e) {
			ygTaskTimeService.saveOrUpdate(TaskMethod.ChangeProductPriceBySecond.name(), runTime, "【秒杀活动更新商品价格】执行失败；" + ExceptionUtil.getExceptionMsg(e));
			try {
				mailUtil.sendWithHtml(new String[]{"sunshuo@yiigoo.cn"}, "秒杀活动更新商品价格任务", ExceptionUtil.getExceptionMsg(e));
			} catch (Exception e1) {
				e1.printStackTrace();
			}
		}
	}

	@Override
	public void doProductSecondJob(Long secondId, String taskType) {
		YgProductSecond productSecond = ygProductSecondService.findWithProductInfoById(secondId);
		Assert.notNull(productSecond, "此秒杀活动不存在");
		Assert.notEmpty(productSecond.getProductList(), "此秒杀活动商品集为空，secondId=" + secondId);
		if ("Start".equals(taskType)) {
			// 活动已经开始，立即更新商品，商品名称添加【今日秒杀】、商品销售价改为秒杀价
			this.updateSalePriceToSecondPrice(productSecond.getProductList());
			this.addProductSecondJob(productSecond.getId(), "End", productSecond.getEndTime(),
					"doProductSecondJob");
		} else if ("End".equals(taskType)) {
			// 活动结束，立即更新商品，商品名称删除【今日秒杀】、商品销售价改为正常销售价
			this.updateSecondPriceToSalePrice(productSecond.getProductList());
		}
	}

	@Override
	public void updateSecondPriceToSalePrice(List<YgProduct4ListModel> productList) {
		List<YgProduct> updateList = new ArrayList<>();
		List<Long> updateIdList = new ArrayList<>();
		Date date2 = new Date();
		productList.forEach(o -> {
			YgProduct ygProduct = new YgProduct();
			ygProduct.setId(o.getId());
			ygProduct.setProductSalePrice(o.getProductSalePrice());
			ygProduct.setVipPrice(o.getVipPrice());
			ygProduct.setProductName(o.getProductName().replace("【今日秒杀】", ""));
			ygProduct.setUpdateBy("秒杀活动");
			ygProduct.setUpdateTime(date2);
			updateList.add(ygProduct);
			updateIdList.add(o.getId());
		});
		ygProductService.updateProductNameAndSalePrice(updateList);
		updateRedisCacheEvict(updateIdList);
	}

	@Override
	public void updateSalePriceToSecondPrice(List<YgProduct4ListModel> productList) {
		List<YgProduct> updateList = new ArrayList<>();
		List<Long> updateIdList = new ArrayList<>();
		Date date2 = new Date();
		productList.forEach(o -> {
			YgProduct ygProduct = new YgProduct();
			ygProduct.setId(o.getId());
			ygProduct.setProductSalePrice(o.getProductSecondPrice());
			ygProduct.setVipPrice(o.getProductSecondPrice().multiply(new BigDecimal("0.95"))
					.setScale(0, BigDecimal.ROUND_DOWN));
			ygProduct.setProductName("【今日秒杀】" + o.getProductName());
			ygProduct.setUpdateBy("秒杀活动");
			ygProduct.setUpdateTime(date2);
			updateList.add(ygProduct);
			updateIdList.add(o.getId());
		});
		ygProductService.updateProductNameAndSalePrice(updateList);
		updateRedisCacheEvict(updateIdList);
	}

	@Override
	public void processSecondBeforeUpdate(Long secondId) {
		YgProductSecond productSecond = ygProductSecondService.findWithProductInfoById(secondId);
		if (new Date().after(productSecond.getStartTime())) {
			// 如果已经开始，先还原商品名称和正常销售价
			this.updateSecondPriceToSalePrice(productSecond.getProductList());
			this.deleteProductSecondJob(secondId, "Start", "processSecondAfterSave");
		}
	}

	@Override
	public void processSecondAfterSave(Long secondId) {
		YgProductSecond productSecond = ygProductSecondService.findWithProductInfoById(secondId);
		Date now = new Date();
		if (now.compareTo(productSecond.getEndTime()) >= 0) {
			// 如果活动提前结束，立即更新商品，商品名称删除【今日秒杀】、商品销售价改为正常销售价
			this.updateSecondPriceToSalePrice(productSecond.getProductList());
			this.deleteProductSecondJob(secondId, "End", "processSecondAfterSave");
		} else {
			Date executeTime;
			String taskType;
			if (now.compareTo(productSecond.getStartTime()) >= 0) {
				// 活动已经开始，立即更新商品，商品名称添加【今日秒杀】、商品销售价改为秒杀价
				this.updateSalePriceToSecondPrice(productSecond.getProductList());
				executeTime = productSecond.getEndTime();
				taskType = "End";
			} else {
				executeTime = productSecond.getStartTime();
				taskType = "Start";
			}
			// 添加定时任务
			this.addProductSecondJob(secondId, taskType, executeTime, "processSecondAfterSave");
		}
	}

	@Override
	public void deleteProductSecondJob(Long secondId, String taskType, String handler) {
		YgQuartzJob job = YgQuartzJob.ProductSecond;
		scheduleJobService.deleteJob(job.getJobName(taskType + "_" + secondId.toString()), job.getJobGroup(),
				"processSecondAfterSave");
	}

	/**
	 * 更新商品缓存信息
	 *
	 * @param updateIdList
	 */
	private void updateRedisCacheEvict(List<Long> updateIdList) {
		if (CollectionUtils.isEmpty(updateIdList)) {
			return;
		}
		updateIdList.forEach(id ->
				redisCacheEvictService.evictAboutProduct(id, null,
						"product.changeProductPriceBySecond"));
	}

	/**
	 * 活动结束，秒杀价改成原销售价
	 * @param date
	 */
	private void updateSecondPriceToSalePrice(Date date) {
		List<YgProduct4ListModel> productList = ygProductSecondService.findBySpecifyDate(date, null);
		if (CollectionUtils.isEmpty(productList)) {
			return;
		}
		logger.info("秒杀活动结束，秒杀价改成原销售价， size:" + productList.size());
		updateSecondPriceToSalePrice(productList);
	}

	/**
	 * 活动开始，原销售价改成秒杀价
	 * @param date
	 */
	private void updateSalePriceToSecondPrice(Date date) {
		List<YgProduct4ListModel> productList = ygProductSecondService.findBySpecifyDate(date, null);
		if (CollectionUtils.isEmpty(productList)) {
			return;
		}
		logger.info("秒杀活动开始，原销售价改成秒杀价， size:" + productList.size());
		updateSalePriceToSecondPrice(productList);
	}

	private void addProductSecondJob(Long secondId, String taskType, Date executeTime, String handler) {
		Map<String, Object> dataMap = new LinkedHashMap<>(2);
		dataMap.put("secondId", secondId);
		dataMap.put("taskType", taskType);
		scheduleJobService.addJob(YgQuartzJob.ProductSecond, taskType + "_" + secondId.toString(),
				executeTime, dataMap, handler);
	}
}
